package net.lab1024.sa.admin.module.business.datasource.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import lombok.extern.slf4j.Slf4j;
import net.lab1024.sa.admin.module.business.datasource.dao.DatasourceDao;
import net.lab1024.sa.admin.module.business.datasource.domain.entity.DatasourceEntity;
import net.lab1024.sa.admin.module.business.datasource.domain.form.DatasourceForm;
import net.lab1024.sa.admin.module.business.datasource.domain.vo.DatasourceVO;
import net.lab1024.sa.admin.module.business.datasource.service.DatasourceService;
import net.lab1024.sa.base.common.domain.ResponseDTO;
import net.lab1024.sa.base.common.code.UserErrorCode;
import net.lab1024.sa.base.common.util.SmartRequestUtil;
import org.springframework.stereotype.Service;

import jakarta.annotation.Resource;
import java.sql.Connection;
import java.sql.DriverManager;
import java.util.Objects;

/**
 * 数据源Service实现
 *
 * @Author 1024创新实验室-主任:卓大
 * @Date 2024-01-01 00:00:00
 * @Wechat zhuoda1024
 * @Email lab1024@163.com
 * @Copyright <a href="https://1024lab.net">1024创新实验室</a>
 */
@Slf4j
@Service
public class DatasourceServiceImpl implements DatasourceService {

    @Resource
    private DatasourceDao datasourceDao;

    @Override
    public ResponseDTO<Page<DatasourceVO>> queryPage(Page<DatasourceVO> page, String name, String type, Integer status) {
        Page<DatasourceVO> result = datasourceDao.queryPage(page, name, type, status);
        return ResponseDTO.ok(result);
    }

    @Override
    public ResponseDTO<DatasourceVO> getDetailById(Long id) {
        DatasourceVO datasourceVO = datasourceDao.getDetailById(id);
        if (Objects.isNull(datasourceVO)) {
            return ResponseDTO.error(UserErrorCode.DATA_NOT_EXIST, "数据源不存在");
        }
        return ResponseDTO.ok(datasourceVO);
    }

    @Override
    public ResponseDTO<String> create(DatasourceForm form) {
        // 检查数据源名称是否已存在
        DatasourceEntity existEntity = datasourceDao.getByName(form.getName(), null);
        if (Objects.nonNull(existEntity)) {
            return ResponseDTO.error(UserErrorCode.ALREADY_EXIST, "数据源名称已存在");
        }

        // 测试连接
        ResponseDTO<String> testResult = testConnection(form);
        if (!testResult.getOk()) {
            return testResult;
        }

        // 创建数据源
        DatasourceEntity entity = BeanUtil.copyProperties(form, DatasourceEntity.class);
        datasourceDao.insert(entity);
        return ResponseDTO.ok("创建成功");
    }

    @Override
    public ResponseDTO<String> update(DatasourceForm form) {
        // 检查数据源是否存在
        DatasourceEntity existEntity = datasourceDao.selectById(form.getId());
        if (Objects.isNull(existEntity)) {
            return ResponseDTO.error(UserErrorCode.DATA_NOT_EXIST, "数据源不存在");
        }

        // 检查数据源名称是否已存在
        DatasourceEntity nameExistEntity = datasourceDao.getByName(form.getName(), form.getId());
        if (Objects.nonNull(nameExistEntity)) {
            return ResponseDTO.error(UserErrorCode.ALREADY_EXIST, "数据源名称已存在");
        }

        // 测试连接
        ResponseDTO<String> testResult = testConnection(form);
        if (!testResult.getOk()) {
            return testResult;
        }

        // 更新数据源
        DatasourceEntity entity = BeanUtil.copyProperties(form, DatasourceEntity.class);
        datasourceDao.updateById(entity);
        return ResponseDTO.ok("更新成功");
    }

    @Override
    public ResponseDTO<String> delete(Long id) {
        // 检查数据源是否存在
        DatasourceEntity entity = datasourceDao.selectById(id);
        if (Objects.isNull(entity)) {
            return ResponseDTO.error(UserErrorCode.DATA_NOT_EXIST, "数据源不存在");
        }

        // 删除数据源
        datasourceDao.deleteById(id);
        return ResponseDTO.ok("删除成功");
    }

    @Override
    public ResponseDTO<String> testConnection(DatasourceForm form) {
        try {
            String url = buildJdbcUrl(form);
            Class.forName(getDriverClassName(form.getType()));
            
            try (Connection connection = DriverManager.getConnection(url, form.getUsername(), form.getPassword())) {
                if (connection.isValid(form.getTimeout())) {
                    return ResponseDTO.ok("连接测试成功");
                } else {
                    return ResponseDTO.error(UserErrorCode.PARAM_ERROR, "连接超时");
                }
            }
        } catch (Exception e) {
            log.error("数据源连接测试失败", e);
            return ResponseDTO.error(UserErrorCode.PARAM_ERROR, "连接测试失败: " + e.getMessage());
        }
    }

    /**
     * 构建JDBC URL
     */
    private String buildJdbcUrl(DatasourceForm form) {
        switch (form.getType().toLowerCase()) {
            case "mysql":
                return String.format("jdbc:mysql://%s:%d/%s?useSSL=false&serverTimezone=UTC&allowPublicKeyRetrieval=true",
                        form.getHost(), form.getPort(), form.getDatabaseName());
            case "oracle":
                return String.format("jdbc:oracle:thin:@%s:%d:%s",
                        form.getHost(), form.getPort(), form.getDatabaseName());
            case "postgresql":
                return String.format("jdbc:postgresql://%s:%d/%s",
                        form.getHost(), form.getPort(), form.getDatabaseName());
            case "sqlserver":
                return String.format("jdbc:sqlserver://%s:%d;databaseName=%s",
                        form.getHost(), form.getPort(), form.getDatabaseName());
            default:
                throw new IllegalArgumentException("不支持的数据库类型: " + form.getType());
        }
    }

    /**
     * 获取驱动类名
     */
    private String getDriverClassName(String type) {
        switch (type.toLowerCase()) {
            case "mysql":
                return "com.mysql.cj.jdbc.Driver";
            case "oracle":
                return "oracle.jdbc.driver.OracleDriver";
            case "postgresql":
                return "org.postgresql.Driver";
            case "sqlserver":
                return "com.microsoft.sqlserver.jdbc.SQLServerDriver";
            default:
                throw new IllegalArgumentException("不支持的数据库类型: " + type);
        }
    }
} 